﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CoolCode.Linq
{
	public interface IPageable<T> : IQueryable<T>, IPageable
	{
		IPaginatedList<T> Paging();
	}

	public class Pageable<T> : IPageable<T>
	{
		private IQueryable<T> source;

		public int PageIndex { get; private set; }
		public int PageSize { get; private set; }
		public int TotalRecords { get; private set; }
		public int PageCount { get; private set; }

		public Pageable(IQueryable source, int pageIndex, int pageSize)
			: this(source.Cast<T>(), pageIndex, pageSize)
		{ }

		public Pageable(IQueryable<T> source, int pageIndex, int pageSize)
		{
			PageIndex = pageIndex < 0 ? 0 : pageIndex;
			PageSize = pageSize < 0 ? 15 : pageSize;
			TotalRecords = source.Count();
			PageCount = (int)Math.Ceiling(TotalRecords / (double)PageSize);
			this.source = source;
		}

		public Pageable(IQueryable<T> source, PageParam p)
			: this(source, p.PageIndex, p.PageSize)
		{
		}



		#region IEnumerable<T> Members

		public IEnumerator<T> GetEnumerator()
		{
			return source.GetEnumerator();
		}

		#endregion

		#region IEnumerable Members

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return ((System.Collections.IEnumerable)source).GetEnumerator();
		}

		#endregion

		#region IQueryable Members

		public Type ElementType
		{
			get { return source.ElementType; }
		}

		public System.Linq.Expressions.Expression Expression
		{
			get { return source.Expression; }
		}

		public IQueryProvider Provider
		{
			get { return source.Provider; }
		}

		#endregion

		#region IPageable<T> Members

		public IPaginatedList<T> Paging()
		{
			return new PaginatedList<T>(source, this.PageIndex, this.PageSize) ;
		}

		#endregion
	}

	public static class IPageableExtensions
	{  
        public static IPageable<T> AsPageable<T>(this IQueryable<T> query, PageParam p)
        {
            return new Pageable<T>(query, p);
        }

	}
}
